package com.ptu.server.Impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ptu.dto.OrderDTO;
import com.ptu.dto.OrderItemDTO;
import com.ptu.entity.*;
import com.ptu.mapper.*;
import com.ptu.server.OrderServer;
import com.ptu.util.PageResult;
import com.ptu.util.UserHolder;
import com.ptu.vo.OrderVO;
import com.ptu.vo.ProductVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

@Slf4j
@Service
public class OrderServerImpl implements OrderServer {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderItemMapper orderItemMapper;

    @Autowired
    AddressMapper addressMapper;

    @Autowired
    ProductMapper productMapper;

    @Autowired
    CartMapper cartMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    CommentMapper commentMapper;


    @Transactional
    @Override
    public Order addOrder(OrderDTO orderDTO) {
        //先从缓存中判断库存是否充足
        for (OrderItemDTO orderItemDTO : orderDTO.getOrderItems()) {
            Long productId = orderItemDTO.getProductId();
            Integer quantity = orderItemDTO.getQuantity();

            // 1. 获取缓存中的库存
            String key = "product:detail:" + productId;
            ProductVO productRedis = (ProductVO) redisTemplate.opsForValue().get(key);
            Integer stock = productRedis.getStock();
            //获取商品名称
            String productName = productRedis.getName();
            // 判断库存是否充足
            if (stock < quantity) {
                // 返回错误信息：库存不足
                System.out.println(productName+"缓存商品库存不足");
                throw new RuntimeException(productName + "商品库存不足" + "剩余" + stock);
            }

            productRedis.setStock(stock - quantity);

            // 2. 扣减缓存中的库存
            System.out.println("扣减缓存库存");
            redisTemplate.opsForValue().set(key, productRedis);

        }


        System.out.println("添加订单");

        Order order = new Order();
        Integer userId = UserHolder.getUser().getId();

        BeanUtils.copyProperties(orderDTO, order);

        order.setUserId(Long.valueOf(userId)); //用户id
        //订单号（时间戳+随机数+用户ID后缀）
        // 只使用时间戳和随机数生成订单号，减少长度
        String orderNo = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ThreadLocalRandom.current().nextInt(1000, 9999);
        //示例：202405121530421234

        order.setOrderNo(orderNo); //订单号
        order.setStatus(0); //订单状态

        //计算总金额,总金额保留两位小数
        //BigDecimal totalAmount = orderDTO.getOrderItems().stream().map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalAmount = orderDTO.getOrderItems()
                .stream()
                .map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .setScale(2, RoundingMode.HALF_UP);
        order.setTotalAmount(totalAmount);
        System.out.println("订单总金额：" + totalAmount);

        orderMapper.insert(order);

        System.out.println("添加订单项");
        //添加订单项
        for (OrderItemDTO orderItemDTO : orderDTO.getOrderItems()) {
            OrderItem orderItem = new OrderItem();
            BeanUtils.copyProperties(orderItemDTO, orderItem);
            orderItem.setOrderId(order.getId());
            orderItemMapper.insert(orderItem);
        }

        //扣减库存并更新缓存
        for (OrderItemDTO orderItemDTO : orderDTO.getOrderItems()) {
            Long productId = orderItemDTO.getProductId();
            Integer quantity = orderItemDTO.getQuantity();

            // 1. 查询数据库获取最新库存
            Product product = productMapper.selectById(productId);
            if (product.getStock() < quantity) {
                // 返回错误信息：库存不足
                throw new RuntimeException("商品库存不足");
            }

            // 2. 更新数据库库存
            product.setStock(product.getStock() - quantity);
            productMapper.updateById(product);

            // 3. 更新Redis缓存
            updateProductCache(productId);
        }

        //清空购物车
        System.out.println("清空购物车");
        cartMapper.deleteByUserId(userId);

        return order;
    }


    /**
     * 更新商品缓存（先删后查）
     */
    private void updateProductCache(Long productId) {
        String key = "product:detail:" + productId;
        // 1. 先删除旧缓存
        //redisTemplate.delete(key);

        // 2. 延迟双删（防止并发问题）
        new Thread(() -> {
            try {
                Thread.sleep(500); // 延迟500ms
                redisTemplate.delete(key);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();

        // 3. 可以异步重新加载缓存（可选）
        // asyncReloadProductCache(productId);
    }

    @Override
    public List<OrderVO> list() {
        System.out.println("获取订单列表");

        Integer userId = UserHolder.getUser().getId();
        // 1. 多表联查订单和评论
        List<OrderVO> orders = orderMapper.listOrdersWithComments(userId);

        // 2. 为每个订单查询订单项
        orders.forEach(order -> {
            List<OrderItem> items = orderItemMapper.listItemsByOrderId(order.getId());
            order.setOrderItems(items);

            // 查询地址信息（新增逻辑）
            if (order.getAddressId() != null) {
                Address address = addressMapper.selectAddressById(order.getAddressId());
                if (address != null) {
                    // 将地址信息填充到 OrderVO 的冗余字段中
                    order.setProvince(address.getProvince());
                    order.setCity(address.getCity());
                    order.setDistrict(address.getDistrict());
                    order.setDetailAddress(address.getDetailedAddress());
                }
            }
        });
        return orders;
    }

    @Override
    public List<OrderVO> allList() {
        System.out.println("获取所有已评论订单列表");

        // 1. 多表联查订单和评论
        List<OrderVO> orders = orderMapper.listOrdersWithCommentsByStatus();

        // 2. 为每个订单查询订单项
        orders.forEach(order -> {
            List<OrderItem> items = orderItemMapper.listItemsByOrderId(order.getId());
            order.setOrderItems(items);
        });
        return orders;
    }


    @Override
    public Order detail(Long id) {
        System.out.println("获取订单详情");
        Order order = orderMapper.detail(id);
        return order;
    }

    @Override
    public void pay(Long id) {
        System.out.println("支付订单");
        //检查订单状态是否为"待支付"
        orderMapper.updatePayStatus(id);
    }

    @Override
    public void payByOrderNo(String orderNo) {
        System.out.println("orderNo支付订单");
        //检查订单状态是否为"待支付"
        orderMapper.updatePayStatusByOrderNo(orderNo);
    }


    @Override
    public void cancel(Long id) {
        System.out.println("取消订单");

        //恢复库存
        System.out.println("恢复redis库存");
        Order order = orderMapper.detail(id);
        List<OrderItem> orderItems = orderItemMapper.listItemsByOrderId(id);
        for (OrderItem orderItem : orderItems) {
            Product product = productMapper.selectById(orderItem.getProductId());
            // 更新数据库库存
            product.setStock(product.getStock() + orderItem.getQuantity());
            productMapper.updateById(product);
            
            // 更新Redis缓存中的库存
            String key = "product:detail:" + orderItem.getProductId();
            ProductVO productRedis = (ProductVO) redisTemplate.opsForValue().get(key);
            if (productRedis != null) {
                productRedis.setStock(productRedis.getStock() + orderItem.getQuantity());
                System.out.println("更新Redis缓存中的库存");

                redisTemplate.opsForValue().set(key, productRedis);
            }
        }
        orderMapper.updateCancelStatus(id);
    }

    @Override
    public void confirm(Long id) {
        System.out.println("确认订单");
        orderMapper.updateConfirmStatus(id);
    }

    @Transactional
    @Override
    public void returnGoods(Long id) {
        System.out.println("退货");
        orderMapper.updateReturnStatus(id);

        //恢复库存
        System.out.println("恢复库存");
        Order order = orderMapper.detail(id);
        List<OrderItem> orderItems = orderItemMapper.listItemsByOrderId(id);
        for (OrderItem orderItem : orderItems) {
            Product product = productMapper.selectById(orderItem.getProductId());
            // 更新数据库库存
            product.setStock(product.getStock() + orderItem.getQuantity());
            productMapper.updateById(product);
            
            // 更新Redis缓存中的库存
            String key = "product:detail:" + orderItem.getProductId();
            ProductVO productRedis = (ProductVO) redisTemplate.opsForValue().get(key);
            if (productRedis != null) {
                productRedis.setStock(productRedis.getStock() + orderItem.getQuantity());
                redisTemplate.opsForValue().set(key, productRedis);
            }
        }
    }

    @Override
    public void deliver(Long id) {
        System.out.println("发货");
        orderMapper.updateDeliverStatus(id);
    }

    @Override
    public PageResult getOrderList(Integer status, String paymentMethod, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<OrderVO> page = orderMapper.adminGetOrderList(status, paymentMethod);
        return new PageResult(page.getTotal(), page.getResult());
    }


    @Override
    public Order adminDetail(Long id) {
        Order order = orderMapper.detail(id);
        //获取订单项
        List<OrderItem> orderItems = orderItemMapper.listItemsByOrderId(id);
        order.setOrderItems(orderItems);
        return order;
    }

    @Override
    public void comment(Long id) {
        orderMapper.updateCommentStatus(id);
    }

    @Override
    public void returnOkGoods(Long id) {
        orderMapper.updateAdminReturnStatus(id);
    }



}
